package com.gxp.framework.manager.factory;

import com.alibaba.fastjson.JSONObject;
import com.gxp.common.config.GxPConfig;
import com.gxp.common.constant.Constants;
import com.gxp.common.utils.*;
import com.gxp.common.utils.spring.SpringUtils;
import com.gxp.framework.shiro.session.OnlineSession;
import com.gxp.system.domain.SysLogininfor;
import com.gxp.system.domain.SysUserOnline;
import com.gxp.system.domain.ZkAudit;
import com.gxp.system.service.ISysUserOnlineService;
import com.gxp.system.service.IZkAuditService;
import com.gxp.system.service.impl.SysLogininforServiceImpl;
import eu.bitwalker.useragentutils.UserAgent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.TimerTask;

/**
 * 异步工厂（产生任务用）
 * 
 * @author liuhulu
 *
 */
public class AsyncFactory
{
    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");

    /**
     * 同步session到数据库
     * 
     * @param session 在线用户会话
     * @return 任务task
     */
    public static TimerTask syncSessionToDb(final OnlineSession session)
    {
        return new TimerTask()
        {
            @Override
            public void run()
            {
                SysUserOnline online = new SysUserOnline();
                online.setSessionId(String.valueOf(session.getId()));
                online.setDeptName(session.getDeptName());
                online.setLoginName(session.getLoginName());
                online.setStartTimestamp(session.getStartTimestamp());
                online.setLastAccessTime(session.getLastAccessTime());
                online.setExpireTime(session.getTimeout());
                online.setIpaddr(session.getHost());
                online.setLoginLocation(AddressUtils.getRealAddressByIP(session.getHost()));
                online.setBrowser(session.getBrowser());
                online.setOs(session.getOs());
                online.setStatus(session.getStatus());
                SpringUtils.getBean(ISysUserOnlineService.class).saveOnline(online);

            }
        };
    }

//    /**
//     * 操作日志记录
//     *
//     * @param operLog 操作日志信息
//     * @return 任务task
//     */
//    public static TimerTask recordOper(final SysOperLog operLog)
//    {
//        return new TimerTask()
//        {
//            @Override
//            public void run()
//            {
//                // 远程查询操作地点
//                operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
//                SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
//            }
//        };
//    }

    /**
     * 记录登录信息
     * 
     * @param username 用户名
     * @param status 状态
     * @param message 消息
     * @param args 列表
     * @return 任务task
     */
    public static TimerTask recordLogininfor(final String username, final String status, final String message, final Object... args)
    {
        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        final String ip = ShiroUtils.getIp();
        return new TimerTask()
        {
            @Override
            public void run()
            {
                String address = AddressUtils.getRealAddressByIP(ip);
                StringBuilder s = new StringBuilder();
                s.append(LogUtils.getBlock(ip));
                s.append(address);
                s.append(LogUtils.getBlock(username));
                s.append(LogUtils.getBlock(status));
                s.append(LogUtils.getBlock(message));
                // 打印信息到日志
                sys_user_logger.info(s.toString(), args);
                // 获取客户端操作系统
                String os = userAgent.getOperatingSystem().getName();
                // 获取客户端浏览器
                String browser = userAgent.getBrowser().getName();
                // 封装对象
                SysLogininfor logininfor = new SysLogininfor();
                logininfor.setLoginName(username);
                logininfor.setIpaddr(ip);
                logininfor.setLoginLocation(address);
                logininfor.setBrowser(browser);
                logininfor.setOs(os);
                logininfor.setMsg(message);
                // 日志状态
                if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
                {
                    logininfor.setStatus(Constants.SUCCESS);
                }
                else if (Constants.LOGIN_FAIL.equals(status))
                {
                    logininfor.setStatus(Constants.FAIL);
                }
                // 插入数据
                SpringUtils.getBean(SysLogininforServiceImpl.class).insertLogininfor(logininfor);
            }
        };
    }

    /**
     * 审计记录
     *
     * @return 任务task
     */
    public static TimerTask recordAudit(final ZkAudit audit)
    {
        return new TimerTask()
        {
            @Override
            public void run()
            {
                // 远程查询操作地点
                SpringUtils.getBean(IZkAuditService.class).insertZkAudit(audit);
            }
        };
    }

    /**
     * 新增审计
     * @param title 审计模块（User And Role， Project， ...）
     * @param type 审计类型（新增， 修改， 删除...）
     * @param wher 操作位置（PC Name/SpinStudio多个用“，”隔开）
     * @param version 版本号
     * @param what 操作内容
     * @param comment 备注
     * @param who 操作人
     * @param role 角色
     * @param ip IP地址
     * @param operStatus 操作结果（成功或者失败，失败带上msg）
     * @param errorMsg 失败信息
     * @param time 操作时间
     * @return 任务task
     */
    public static TimerTask recordAudit(String title, int type, String wher, String version, String what, String comment, String who, String role, String ip, String operStatus, String errorMsg, String auditParams, Date time)
    {
        ZkAudit audit = new ZkAudit();
        audit.setTitle(title);
        audit.setType(type);
        audit.setWher(wher);
        audit.setVersion(version);
        audit.setWhat(what);
        audit.setComment(comment);
        audit.setWho(who);
        audit.setIp(ip);
        audit.setOperStatus(operStatus);
        audit.setErrorMsg(errorMsg);
        //json字符串转json对象
        JSONObject jsonObject = JSONObject.parseObject(auditParams);
        if(jsonObject != null && jsonObject.containsKey("entityId")){
            //带上实体Id
            audit.setEntityId(jsonObject.getLong("entityId"));
            //移除固定属性
            jsonObject.remove("entityId");
            audit.setAuditParams(StringUtils.substring(jsonObject.toJSONString(), 0, 2000));
        }else {
            audit.setAuditParams(auditParams);
        }
        audit.setTime(time);
        audit.setRole(role);

        return recordAudit(audit);
    }

    public static TimerTask recordAudit(String title, int type, String what, String operStatus, String errorMsg, String auditParams)
    {
        //操作人
        String who = ShiroUtils.getLoginName();
        String role = ShiroUtils.getRoleNames();
        return recordAudit(title, type, what, who, role, operStatus, errorMsg, auditParams);
    }

    public static TimerTask recordAuditSuccess(String title, int type, String what, String auditParams)
    {
        //操作人
        String who = ShiroUtils.getLoginName();
        String role = ShiroUtils.getRoleNames();
        return recordAudit(title, type, what, who, role, Constants.SUCCESS, "", auditParams);
    }

    public static TimerTask recordAuditFail(String title, int type, String what, String errorMsg, String auditParams)
    {
        //操作人
        String who = ShiroUtils.getLoginName();
        String role = ShiroUtils.getRoleNames();
        return recordAudit(title, type, what, who, role, Constants.FAIL, errorMsg, auditParams);
    }

    public static TimerTask recordAudit(String title, int type, String what, String who, String role, String operStatus, String errorMsg, String auditParams)
    {
        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        // 获取客户端浏览器
        String browser = userAgent.getBrowser().getName();
        String wher = browser;
        //系统版本号
        String version = GxPConfig.getVersion();
        //ip
        String ip = ShiroUtils.getIp();
        return recordAudit(title, type, wher, version, what, "", who, role, ip, operStatus, errorMsg, auditParams, DateUtils.getNowDate());
    }
}
